package com.stone.starter.core.helper;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * threadlocal帮助器
 *
 * @author Mr_wenpan@163.com 2021/06/01 19:56
 */
public class ThreadLocalHelper {

    private static final ThreadLocal<Map<String, String>> THREAD_LOCAL_MAP = new InheritableThreadLocal<>();

    /**
     * 获取ThreadLocal的强引用，这个方法一般不建议直接调用
     *
     * @return java.lang.ThreadLocal
     * @date 2021/6/10 4:29 下午
     * @author Mr_wenpan@163.com
     */
    public static ThreadLocal<Map<String, String>> getThreadLocalReference() {
        return THREAD_LOCAL_MAP;
    }

    /**
     * 获取当前线程中的map集合
     *
     * @return java.util.Map<java.lang.String, java.lang.String>
     * @date 2021/6/10 4:27 下午
     * @author Mr_wenpan@163.com
     */
    public static Map<String, String> getThreadLocalMap() {
        Map<String, String> map = THREAD_LOCAL_MAP.get();
        if (map == null) {
            map = new HashMap<>();
        }
        return map;
    }

    /**
     * 获取threadlocal上下文中所有的value
     *
     * @return java.util.List<java.lang.String>
     * @date 2021/6/10 4:43 下午
     * @author Mr_wenpan@163.com
     */
    public static List<String> getValues() {
        return (List<String>) getThreadLocalMap().values();
    }

    /**
     * 通过key获取map中的值
     *
     * @param key key
     * @return java.lang.String
     * @date 2021/6/10 4:19 下午
     * @author Mr_wenpan@163.com
     */
    public static String get(String key) {
        Map<String, String> threadLocalMap = getThreadLocalMap();
        return threadLocalMap.get(key);
    }

    /**
     * 批量添加
     *
     * @param map 要添加到threadlocal上下文中的map中的数据集合，默认空key不添加（可自己扩展）
     * @date 2021/6/10 4:13 下午
     * @author Mr_wenpan@163.com
     */
    public static void batchPut(Map<String, String> map) {
        if (map == null) {
            return;
        }
        Map<String, String> localMap = getThreadLocalMap();
        map.forEach((key, value) -> {
            if (key != null) {
                localMap.put(key, value);
            }
        });
    }

    /**
     * 保存变量值到threadlocal，为了保证普适性这里禁止put的key为空
     *
     * @param key   要put到map中的key
     * @param value 要put到map中的value
     * @date 2021/6/10 4:08 下午
     * @author Mr_wenpan@163.com
     */
    public static void put(String key, String value) {
        if (key == null) {
            return;
        }
        Map<String, String> threadLocalMap = getThreadLocalMap();
        threadLocalMap.put(key, value);
    }

    /**
     * 如果不存在才put
     *
     * @param key   key
     * @param value 值
     * @date 2021/6/10 4:35 下午
     * @author Mr_wenpan@163.com
     */
    public static void putIfAbsent(String key, String value) {
        Map<String, String> threadLocalMap = getThreadLocalMap();
        threadLocalMap.putIfAbsent(key, value);
    }

    public static boolean containsKey(String key) {
        Map<String, String> threadLocalMap = getThreadLocalMap();
        return threadLocalMap.containsKey(key);
    }

    public static boolean containsValue(String value) {
        Map<String, String> threadLocalMap = getThreadLocalMap();
        return threadLocalMap.containsValue(value);
    }

    /**
     * 按key清除threadlocal上下文中的值
     *
     * @param key key
     * @date 2021/6/10 4:08 下午
     * @author Mr_wenpan@163.com
     */
    public static void remove(String key) {
        if (key == null) {
            return;
        }
        Map<String, String> threadLocalMap = getThreadLocalMap();
        threadLocalMap.remove(key);
    }

    /**
     * 清除threadlocal上下文中的map保存的所有值
     *
     * @date 2021/6/10 4:16 下午
     * @author Mr_wenpan@163.com
     */
    public static void removeAll() {
        Map<String, String> threadLocalMap = getThreadLocalMap();
        if (threadLocalMap.size() >= 1) {
            threadLocalMap.clear();
        }
    }

    /**
     * 清空threadlocal的引用，防止内存泄漏
     */
    public static void clear() {
        THREAD_LOCAL_MAP.remove();
    }

    public static void clearMap() {
        removeAll();
    }

    /**
     * 覆盖threadlocal中的原有map，默认空map不覆盖
     *
     * @param map map集合
     * @date 2021/6/10 4:51 下午
     * @author wenpan
     */
    public void set(Map<String, String> map) {
        if (map == null) {
            return;
        }
        getThreadLocalReference().set(map);
    }

    /**
     * 强制set，强制使用参数map替换threadlocal中原有的map
     *
     * @param map      map集合
     * @param forceSet 是否强制覆盖，为true时map为空也会覆盖。为false时map为空不会覆盖
     * @date 2021/6/10 4:53 下午
     * @author wenpan
     */
    public void set(Map<String, String> map, boolean forceSet) {
        if (map == null && forceSet) {
            getThreadLocalReference().set(map);
            return;
        }
        if (!forceSet && map == null) {
            return;
        }
        set(map);
    }

    /**
     * 释放threadlocal上下文map引用
     *
     * @date 2021/6/10 4:50 下午
     * @author wenpan
     */
    public static void releaseMap() {
        // 清空map
        clearMap();
        // 清空threadlocal的引用
        clear();
    }
}
